function ProcessLjComment(commentText) {
	//список названий, которые могут быть названиями мест
	var placesCandidates = new Array()

	//список объектов найденных мест
	var places = new Array()

	//положительные и негативные оценки, найденные в комментарии
	var positiveRank = 0;
	var negativeRank = 0;

	//считаем оценки
	processPositiveRank(commentText);
	processNegativeRank(commentText);
	places.push(positiveRank);
	places.push(negativeRank);

	//прогоняем строку по различным методам поиска
	ProcessUpperCaseWords(commentText);
	ProcessLinks(commentText);
	ProcessQuotes(commentText);
	ProcessAddresses(commentText);
	ProcessPlacePrefixes(commentText);
	//print(placesCandidates);

	geocodeCandidates(placesCandidates);

	/** output: 
	* array:
	* 0 - positive rank
    * 1 - negative rank
	* 2,.. - places
	*/
	
	return places;	
	

	//добавляет кандидата в список кандидатов, отсеивая мусор
	function addCandidate(placeCandidateName) {
	//отсеиваем шлак типа адресов картинок, тэгов и путей
	if(placeCandidateName.search(/(.jpg)|(.gif)|(.html)|(.htm)|(nofollow)|(_blank&quot)|(&mdash)|(^[0-9 .,]+$)|([<>=])|(\/)/i) == -1){	
		if(placeCandidateName.search('"') != -1){			
			placeCandidateName = placeCandidateName.slice(0,-2); //удаляем '\"' в конце имени, если это просочилось.
		}		
		placesCandidates.push(placeCandidateName);
	}
	}

	/*
	отправляет запрос на GoogleMaps, разбирает ответ, 
	если такое место нашлось, до добавляет его в места
	*/
	function geocodeCandidates(candidates) {
	for(var i=0; i<candidates.length; i++) {
		response = GoogleMapsRequest(candidates[i]);
	

		//print(response); //debug
		response = response.slice(0, -6); //отсекаем '0' в конце ответа	(так возвращает геокодер)
		
		try{
			responseObj = JSON.parse(response);
		} catch(e) {
			return; //если не удалось распарсить, то забиваем
		}

	
		//look: http://code.google.com/intl/ru/apis/maps/documentation/geocoding/#GeocodingResponses

		if (responseObj.Status.code !=200){
			print("- "+candidates[i])
			continue;
		}
		
		//Нашли, но нашли всего лишь город, а не конкретное место
		var townLevelAccuracy = 6;		
		placemark = responseObj.Placemark[0];
		if (placemark.AddressDetails.Accuracy <= townLevelAccuracy){
			print("? "+candidates[i])
			continue;
		}

		placeName = responseObj.name;
		address = placemark.address;
		address = address.replace("&","");
		longitude = placemark.Point.coordinates[0];
		latitude = placemark.Point.coordinates[1];

		place = {	"name": candidates[i],
					"address": address,
					"latitude": latitude,
					"longitude": longitude };

		//print(JSON.stringify(place));
		places.push(place);
	}
	}

	//Ищет положительные оценки в комментарии
	function processPositiveRank(commentText) {
		while(true){
			//слова, повышающие оценку
			var positiveKeywords = [ "отличн", "\\+", "замечат", "здоров", "супер", "хорош", "прекрасн", "неплох", "ништяк", "отменн", "годн"];			
			keywordLength = 0;
	
			//позиция первого из ключевых слов в строке  
			firstFoundedPos = commentText.length;		
	
			for(var i = 0; i < positiveKeywords.length; i++) {	
				n = commentText.search(new RegExp(positiveKeywords[i],'i'));
				if(n != -1 && n < firstFoundedPos) {
					firstFoundedPos = n;
					keywordLength = positiveKeywords[i].length;
				}
			}
	
		    if(keywordLength > 0) {
				commentText = commentText.slice(firstFoundedPos + keywordLength, -1);
				++positiveRank;
			} else {
				break;
			}
		}	
	}

	//Ищет негативные оценки в комментарии
	function processNegativeRank(commentText) {
		while(true){
			//слова, понижающие оценку
			var negativeKeywords = [ "ужас", "плох", "кошмар", "жут", "уебищ", "погано", "скучн", "говн"];			
			keywordLength = 0;
	
			//позиция первого из ключевых слов в строке  
			firstFoundedPos = commentText.length;		
	
			for(var i = 0; i < negativeKeywords.length; i++) {	
				n = commentText.search(new RegExp(negativeKeywords[i],'i'));
				if(n != -1 && n < firstFoundedPos) {
					firstFoundedPos = n;
					keywordLength = negativeKeywords[i].length;
				}
			}
	
		    if(keywordLength > 0) {
				commentText = commentText.slice(firstFoundedPos + keywordLength, -1);
				++negativeRank;
			} else {
				break;
			}
		}			
	}

	//Ищем все слова/словосочетания слов с большой буквы
	function ProcessUpperCaseWords(commentText) {
	//коэффициент, определяющий, насколько далеко должно быть
	//следующее слово с большой буквы, чтобы считать это 
	//одним названием.		
	var wordsDistance = 15;
	
	while(true){
		n = commentText.search(/[^,.?!:;<>] [A-ZА-Я].*[ .,?!/:;()]/);
	    if(n == -1) break;
	    tmp = commentText.slice(n+2,-1);

		//ищем следующие за ним слова с большой буквы
		n2 = tmp.search(/[^,.?!:;<>] [A-ZА-Я].*[ .,?!/:;()]/); 
		if(n2 == -1 || n2 > wordsDistance){
			n3 = tmp.search(/[ .,?!<>/()]/); //таких слов нет, ограничимся этим
			res = tmp.slice(0, n3);
			commentText = tmp.slice(n3+1, -1); 
		} else {
		    tmp2 = tmp.slice(n2+2,-1);  //нашли, ищем конец этой последовательности
			n3 = tmp2.search(/[ .,?!</;:()]/);
			res = tmp.slice(0, n2+2+n3); 
			commentText = tmp2.slice(n2+3+n3, -1);
		}

		addCandidate(res);
	}	
	}

	//Ищем всё <а>подписи</a> к ссылкам 
	function ProcessLinks(commentText){
	while(true) {
		n = commentText.search(/>[^<>]*<\/a>/);
	    if(n == -1) break;
	    tmp = commentText.slice(n+1,-1);
		n2 = tmp.search(/<\/a>/);
		res = tmp.slice(0, n2);
		commentText = tmp;
		addCandidate(res);
	}	
	}	

	//Ищем всё, "заключённое в кавычки"
	function ProcessQuotes(commentText){
	while(true) {
		n = commentText.search("\"");
	    if(n == -1) break;
	    tmp = commentText.slice(n+1,-1);
		n2 = tmp.search("\"");
		res = tmp.slice(0, n2-1);	
		commentText = tmp.slice(n2, -1);	
	
		//не учитываем адреса и большие строки (вероятно найденные ошибочно)
		if(res.search(/http:/) != 0 && res.length < 50) {
			addCandidate(res);
		}
	}	
	}

	//Ищем всё, похожее на адрес
	function ProcessAddresses(commentText){
	while(true) {
		//различные префиксы адреса
		var addressKeyWords = [ "ул\\.", "пр\\.", "пл\\.", "площад", "просп\\.", "проспект ", "улица ", "бул\\ ", "бульвар ", "пер\\.", "переулок ", "линия", "наб\\.", "набережная"];
		
		keywordLength = 0;	
		//позиция первого из ключевых слов в строке  
		firstFoundedPos = commentText.length;		
		n = -1;
		for(var i = 0; i < addressKeyWords.length; i++) {	
			n = commentText.search(new RegExp(addressKeyWords[i],'i'));
			
			if(n != -1 && n < firstFoundedPos) {				
				firstFoundedPos = n;
				keywordLength = addressKeyWords[i].length;
			}
		}
	
	    if(keywordLength == 0) {
			 break;		
		}

	    res = commentText.slice(firstFoundedPos, -1);		
	    tmp = commentText.slice(firstFoundedPos + keywordLength, -1);
		n2 = tmp.search(/[0-9]+/); //пытаемся найти номер дома

		notHouseNumberDistance = 25; //максимальное расстояние от префикса до номера дома.
		nameBeforePrefixDistance = 20; //максимальная длина названия улицы, если оно до префикса
		houseNumberMinDistance = 5; //минимальное расстояние, при котором считается что название улицы между префиксом и номером.

        if(n2 == -1 || n2 > notHouseNumberDistance)    //если не вышло, то цепляемся хотя бы за улицу/проспект
		{
			n2 = tmp.search(/[^A-Za-zА-Яа-я]/);
		} else{
			tmp2 = tmp.slice(n2, -1);		//ищем конец номера дома 		
			n2 = n2 + tmp2.search(/[ .!?:;<>()]/);

			if(n2 < houseNumberMinDistance) {      //если номер дома сразу после 'пр.', то ищем название слева				
				tmp2 = commentText.slice(firstFoundedPos - nameBeforePrefixDistance, firstFoundedPos + keywordLength + n2);             	
				n = tmp2.search(/[A-ZА-Я]/);
				if(n != -1){	
					res = tmp2.slice(n, -1);	
				}
			} else {
				res = res.slice(0, n2 + keywordLength);	
			}
		} 	
		
		commentText = tmp.slice(n2 + 1, -1);			
		
		addCandidate(res);	
		}		
	}	

	
	//Ищем различные заведения и достопремичательности
	function ProcessPlacePrefixes(commentText){
	while(true) {
		//различные типы заведений
		var placesKeyWords = [ "кафе", "бар", "ресторан", "памятник", "музей", "выставка", "храм", "церковь", "гостинница", "театр" ];		
		keywordLength = 0;	
		//позиция первого из ключевых слов в строке  
		firstFoundedPos = commentText.length;		
		n = -1;
		for(var i = 0; i < placesKeyWords.length; i++) {	
			n = commentText.search(new RegExp(placesKeyWords[i],'i'));
			if(n != -1 && n < firstFoundedPos) {
				firstFoundedPos = n;
				keywordLength = placesKeyWords[i].length;
			}
		}
	
	    if(keywordLength > 0) {
	    	tmp = commentText.slice(firstFoundedPos + keywordLength + 1, -1);
			n2 = tmp.search(/[^а-яА-Яa-zA-Z]/);			
	        if(n2 != -1){	
				res = commentText.slice(firstFoundedPos, firstFoundedPos + keywordLength + n2 + 1);					
				addCandidate(res);		
			}
			commentText = tmp.slice(n2 + 1, -1);			
		}else{
			break;
		}	
	}	
	}
}

